AnnotationConfigApplicationContext另一种方式,可以直接传入所需扫描的包。该容器会将扫描该包及其子包下所有类,并通过默认的过滤器将配置了@Component、@Service等注解的类转换成BeanDefinition,并注册。

开始扫描

整体来说,扫描包跟注册指定bean,多了一个步骤就是:根据包扫描到BeanDefinition。后续两者相差不多。即:

  1. 扫描指定包下的类
  2. 解析元数据信息,如作用域
  3. 对bean定义的通用注解处理
  4. 对qualifiers数据处理(扫描包没有该步骤)
  5. 根据作用域创建代理对象
  6. 注册BeanDefinition

上述步骤,1、2、4、5、6跟注册指定bean一致,可前往上一章查看,本章的目的则在于简述第0步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public int scan(String... basePackages) {
// 获取容器中已注册BeanDefinition个数
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

// 启动扫描
doScan(basePackages);

// 特殊注册注解配置(annotation config)处理器
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

// 返回本次所注册的BeanDefinition个数
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 存放所有扫描到的BeanDefinition
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 遍历指定的包
for (String basePackage : basePackages) {
// 调用父类方法,扫描BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历所扫描到的BeanDefinition,后续就跟注册指定bean有点像了。
for (BeanDefinition candidate : candidates) {
// 获取@Scope的值,即作用域。
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 生成bean的名字
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

// 如果扫描到的bean不是注解bean,则为bena设置默认值,即bean的自动依赖注入属性。
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 如果扫描到的bean是注解bean,则处理其通用注解@Lazy、@Primary等
if (candidate instanceof AnnotatedBeanDefinition) {
// 在上一章已经简述了
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 根据bean名字检查bean是否需要注册,是否在容器中存在冲突
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 根据作用域生成代理类
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 向容器中注册
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}

扫描指定包下的类

具体扫描由ClassPathScanningCandidateComponentProvider实现,其中findCandidateComponents()方法也只能看个步骤,因为大部分内容通过汇编实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}

private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {
// 用于保存的扫描到的BeanDefinition
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
Set<String> types = new HashSet<>();
// 在该类构造中会初始化默认扫描规则,即includeFilters
// 包含@Component、@Repository、@Service、@Controller的bean,以及@ManagedBean、@Name
for (TypeFilter filter : this.includeFilters) {
String stereotype = extractStereotype(filter);
if (stereotype == null) {
throw new IllegalArgumentException("Failed to extract stereotype from "+ filter);
}
types.addAll(index.getCandidateTypes(basePackage, stereotype));
}
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (String type : types) {
// 过去指定资源下的元数据读取器,通过汇编读取资源元信息
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
// 判断扫描的类,是否符合容器所配置的过滤规则
if (isCandidateComponent(metadataReader)) {
// 通过汇编读取字节码中的bean定义元信息
AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition(
metadataReader.getAnnotationMetadata());
// 判断扫描的类,是否符合容器所配置的过滤规则,则添加
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Using candidate component class from index: " + type);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + type);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because matching an exclude filter: " + type);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}

大致内容就是,可分为两步

  1. 在类的构造中初始化扫描规则,即对excludeFilters、includeFilters的赋值,注意@Service、@Controller为组合注解。
  2. 通过汇编读取字节码中的元信息后,判断是否为所需扫描的类,源码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    // 判断是否处于过滤规则中,则返回false
    for (TypeFilter tf : this.excludeFilters) {
    if (tf.match(metadataReader, getMetadataReaderFactory())) {
    return false;
    }
    }
    // 判断是否处于所需扫描的类中,则返回true
    for (TypeFilter tf : this.includeFilters) {
    if (tf.match(metadataReader, getMetadataReaderFactory())) {
    return isConditionMatch(metadataReader);
    }
    }
    return false;
    }